﻿/*******************************************************************************
*	Copyright (C) 2019, Intergraph. All rights reserved.
*	File: BallValve.cs
*  	Creation Date
*	11.04.2019
*	Description: This class module is the implementation of SP3DJacketBallValve C# Symbol.
*	             This class inherits from CustomSymbolDefinition.
*  Change History:
*  dd.mmm.yyyy    who    change description
*******************************************************************************/

using System;
using System.IO;
using System.Collections.ObjectModel;
using Ingr.SP3D.Common.Middle;
using Ingr.SP3D.Common.Middle.Services;
using Ingr.SP3D.Common.Exceptions;
using Ingr.SP3D.CommonSymbolFunctions;
using Ingr.SP3D.ReferenceData.Middle;
using System.Windows.Forms;
using Ingr.SP3D.Equipment.Middle;

namespace Ingr.SP3D.SEIDDP
{
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //   ProgID: SEIDDP,Ingr.SP3D.SEIDDP.LG01
    //   Author:  Yuanpeng Zhang 
    //   Description: DIS01

    //   Change History:
    //   version        data              who                change description
    //   =======        ===========       ==============     ==========================================================================================
    //   2.0.0.2        2023-03-28        Yuanpeng Zhang     VB -> .net
    //   2.0.0.3        2024-06-07        xingheng yu        重新定义了D4的概念
    //   2.0.0.4        2024-07-02        xingheng yu        增加里D11 D12
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    [CacheOption(CacheOptionType.NonCached)]
    [VariableOutputs]
    [SymbolVersion("2.0.0.4")]
    public class DIS01 : CustomSymbolDefinition //继承后者的类
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public DIS01() : base()
        {
            //有多少个port，就会重复进来多少次
            //这个dll就类似于pid的datasource对象           
            string DllPath = MiddleServiceProvider.SiteMgr.ActiveSite.ActivePlant.PlantCatalog.SymbolShare + @"\Custom Symbols\CommonSymbolFunctions.dll";
            if (File.Exists(DllPath) == false)
            {
                throw new Exception(@"SharedContent\Custom Symbols\CommonSymbolFunctions.dll 未找到，symbol无法工作");
            }
            else
            {
                Ingr.SP3D.Content.CommonSymbolFunctionLoader.Load();
            }
            defaultPartDataBasis = 15;
        }

        //DefinitionName/ProgID of this symbol is SEIDDP,Ingr.SP3D.SEIDDP.DIS01
        SymbolGeometryHelper oGemHelper = new SymbolGeometryHelper();
        double parD2, parInsulationThickness, parD4, parD5, parD6, parD7, parD8, parD9, parD10;
        /// <summary>
        /// 盒子的高度
        /// </summary>
        double parD11;
        /// <summary>
        /// 盒子的长度
        /// </summary>
        double parD12;
        int defaultPartDataBasis;
        double parPortIndex3, parPortIndex2, parPortIndex1, parNpd3, parNpd2, parNpd1;
        int parEndPreparation1, parScheduleThickness1, parEndStandard1, parPressureRating1, parFlowDirection1,
            parEndPreparation2, parScheduleThickness2, parEndStandard2, parPressureRating2, parFlowDirection2,
            parEndPreparation3, parScheduleThickness3, parEndStandard3, parPressureRating3, parFlowDirection3;
        string parNpdUnitType1, parId1, parNpdUnitType2, parId2, parNpdUnitType3, parId3;

        #region "Definition of Inputs" 
        //这个1 2 3 4代表了唯一的序号，先后顺序。因为所有的输入参数被视为一个集合
        //名字要和bulkload表里的属性名字一致。顺序、描述其实无所谓,外部的参数会根据Name自动匹配到对应的某一个参数中。
        [InputCatalogPart(1)]
        //默认这个是1
        public InputCatalogPart m_oPartDef;
        [InputDouble(2, "FacetoFace", "Face to Face Distance", 1, true)]
        public InputDouble m_D2;
        [InputDouble(3, "InstrumentHeight3", "No Use In SPI Group", 0.1)]
        public InputDouble m_D3;
        [InputDouble(4, "InstrumentHeight4", "D4", 0.2)]
        public InputDouble m_D4;
        [InputDouble(5, "InstrumentHeight5", "D5", 0.5, true)]
        public InputDouble m_D5;
        [InputDouble(6, "InstrumentHeight6", "D6", 0.5, true)]
        public InputDouble m_D6;
        [InputDouble(7, "InsulationThickness", "InsulationThickness", 0.25, true)]
        public InputDouble m_InsulationThickness;


        [InputDouble(8, "Npd", "Npd", 100, true)]
        public InputDouble m_Npd;
        [InputDouble(9, "EndPreparation", "End Preparation", 21, true)]
        public InputDouble m_EndPreparation;
        [InputDouble(10, "ScheduleThickness", "Schedule Thickness", 100, true)]
        public InputDouble m_ScheduleThickness;
        [InputDouble(11, "EndStandard", "End Standard", 5, true)]
        public InputDouble m_EndStandard;
        [InputDouble(12, "PressureRating", "Pressure Rating", 35, true)]
        public InputDouble m_PressureRating;
        [InputDouble(13, "FlowDirection", "Flow Direction", 3, true)]
        public InputDouble m_FlowDirection;
        [InputString(14, "NpdUnitType", "Npd Unit Type", "mm", true)]
        public InputString m_NpdUnitType;

        //port的话  9个一组
        [InputDouble(15, "PortIndex1", "Port Index 1", 1, true)]
        public InputDouble m_PortIndex1;
        [InputDouble(16, "Npd1", "Npd 1", 0, true)]
        public InputDouble m_Npd1;
        [InputDouble(17, "EndPreparation1", "End Preparation 1", 0, true)]
        public InputDouble m_EndPreparation1;
        [InputDouble(18, "ScheduleThickness1", "Schedule Thickness 1", 0, true)]
        public InputDouble m_ScheduleThickness1;
        [InputDouble(19, "EndStandard1", "End Standard 1", 0, true)]
        public InputDouble m_EndStandard1;
        [InputDouble(20, "PressureRating1", "Pressure Rating 1", 0, true)]
        public InputDouble m_PressureRating1;
        [InputDouble(21, "FlowDirection1", "Flow Direction 1", 0, true)]
        public InputDouble m_FlowDirection1;
        [InputString(22, "Id1", "Id 1", "VNoz1", true)]
        public InputString m_Id1;
        [InputString(23, "NpdUnitType1", "Npd Unit Type 1", "", true)]
        public InputString m_NpdUnitType1;


        [InputDouble(24, "PortIndex2", "Port Index 2", 2, true)]
        public InputDouble m_PortIndex2;
        [InputDouble(25, "Npd2", "Npd 2", 0, true)]
        public InputDouble m_Npd2;
        [InputDouble(26, "EndPreparation2", "End Preparation 2", 0, true)]
        public InputDouble m_EndPreparation2;
        [InputDouble(27, "ScheduleThickness2", "Schedule Thickness 2", 0, true)]
        public InputDouble m_ScheduleThickness2;
        [InputDouble(28, "EndStandard2", "End Standard 2", 0, true)]
        public InputDouble m_EndStandard2;
        [InputDouble(29, "PressureRating2", "Pressure Rating 2", 0, true)]
        public InputDouble m_PressureRating2;
        [InputDouble(30, "FlowDirection2", "Flow Direction 2", 0, true)]
        public InputDouble m_FlowDirection2;
        [InputString(31, "Id2", "Id 2", "VNoz2", true)]
        public InputString m_Id2;
        [InputString(32, "NpdUnitType2", "Npd Unit Type 2", "", true)]
        public InputString m_NpdUnitType2;


        [InputDouble(33, "PortIndex3", "Port Index 3", 3, true)]
        public InputDouble m_PortIndex3;
        [InputDouble(34, "Npd3", "Npd 3", 0, true)]
        public InputDouble m_Npd3;
        [InputDouble(35, "EndPreparation3", "End Preparation 3", 0, true)]
        public InputDouble m_EndPreparation3;
        [InputDouble(36, "ScheduleThickness3", "Schedule Thickness 3", 0, true)]
        public InputDouble m_ScheduleThickness3;
        [InputDouble(37, "EndStandard3", "End Standard 3", 0, true)]
        public InputDouble m_EndStandard3;
        [InputDouble(38, "PressureRating3", "Pressure Rating 3", 0, true)]
        public InputDouble m_PressureRating3;
        [InputDouble(39, "FlowDirection3", "Flow Direction 3", 0, true)]
        public InputDouble m_FlowDirection3;
        [InputString(40, "Id3", "Id 3", "VNoz3", true)]
        public InputString m_Id3;
        [InputString(41, "NpdUnitType3", "Npd Unit Type 3", "", true)]
        public InputString m_NpdUnitType3;


        [InputDouble(42, "InstrumentHeight7", "InstrumentHeight7", 0.1, true)]
        public InputDouble m_D7;
        [InputDouble(43, "InstrumentHeight8", "InstrumentHeight8", 0.5, true)]
        public InputDouble m_D8;
        [InputDouble(44, "InstrumentHeight9", "InstrumentHeight9", 0.5, true)]
        public InputDouble m_D9;
        [InputDouble(45, "ActuatorRotation1", "ActuatorRotation1", 0, true)]
        public InputDouble m_D10;
        [InputDouble(46, "IndicatorHeight1", "IndicatorHeight1", 0.1, true)]
        public InputDouble m_D11;
        [InputDouble(47, "IndicatorLength", "IndicatorLength", 0.1, true)]
        public InputDouble m_D12;
        #endregion

        #region "Definitions of Aspects and their Outputs"
        //名字要在实际outputs.add时，匹配上
        [Aspect("Physical", "Physical", AspectID.SimplePhysical)]
        [SymbolOutput("LeftCone", "主体圆柱")]
        [SymbolOutput("Cone1", "下方圆台")]
        [SymbolOutput("Cone2", "上方的圆台")]
        [SymbolOutput("Cylinder2", "像法兰一样的两片东西")]
        [SymbolOutput("Branch1", "port1上的连接杆")]
        [SymbolOutput("Branch2", "port2上的连接杆")]
        [SymbolOutput("Branch3", "旋转的杆子（接主体的）")]
        [SymbolOutput("Branch4", "旋转的杆子（接末端的小box）")]
        [SymbolOutput("Box", "Box")]
        [SymbolOutput("PNoz1", "Nozzle with out Length")]
        [SymbolOutput("PNoz2", "Nozzle with out Length")]
        [SymbolOutput("PNoz3", "Nozzle with out Length")]
        public AspectDefinition m_Physical;  //Aspect可以理解为SymbolOutput的集合

        [Aspect("Insulation", "Insulation", AspectID.Insulation)]
        [SymbolOutput("InsulationCylinder", "Cylinder")]
        public AspectDefinition m_Insulation;

        #endregion

        #region "Construct Outputs"

        /// <summary>
        /// 造型
        /// </summary>
        protected override void ConstructOutputs()
        {
            try
            {
                parD2 = m_D2.Value;
                parInsulationThickness = m_InsulationThickness.Value;
                parD4 = m_D4.Value;//24 06 07改
                parD5 = m_D5.Value;
                parD6 = m_D6.Value;
                parD7 = m_D7.Value;
                parD8 = m_D8.Value;
                parD9 = m_D9.Value;
                parD10 = m_D10.Value;
                parD11 = m_D11.Value;
                parD12 = m_D12.Value;
                // 角度会自动变为弧度进来
                // 长度会自动变为m为单位进来

                var TEST = m_FlowDirection.Value;
                //一组里
                parPortIndex1 = m_PortIndex1.Value;
                parNpd1 = m_Npd1.Value;
                parEndPreparation1 = (int)m_EndPreparation1.Value;
                parScheduleThickness1 = (int)m_ScheduleThickness1.Value;
                parEndStandard1 = (int)m_EndStandard1.Value;
                parPressureRating1 = (int)m_PressureRating1.Value;
                parFlowDirection1 = (int)m_FlowDirection1.Value;
                parId1 = m_Id1.Value;
                parNpdUnitType1 = m_NpdUnitType1.Value;

                parPortIndex2 = m_PortIndex2.Value;
                parNpd2 = m_Npd2.Value;
                parEndPreparation2 = (int)m_EndPreparation2.Value;
                parScheduleThickness2 = (int)m_ScheduleThickness2.Value;
                parEndStandard2 = (int)m_EndStandard2.Value;
                parPressureRating2 = (int)m_PressureRating2.Value;
                parFlowDirection2 = (int)m_FlowDirection2.Value;
                parId2 = m_Id2.Value;
                parNpdUnitType2 = m_NpdUnitType2.Value;

                parPortIndex3 = m_PortIndex3.Value;
                parNpd3 = m_Npd3.Value;
                parEndPreparation3 = (int)m_EndPreparation3.Value;
                parScheduleThickness3 = 1; //(int)m_ScheduleThickness3.Value;
                parEndStandard3 = (int)m_EndStandard3.Value;
                parPressureRating3 = (int)m_PressureRating3.Value;
                parFlowDirection3 = (int)m_FlowDirection3.Value;
                parId3 = m_Id3.Value;
                parNpdUnitType3 = m_NpdUnitType3.Value;

                PipeComponent DDP = (PipeComponent)m_oPartDef.Value;  //Get the part from the catalog
                SP3DConnection connection = this.OccurrenceConnection;
                //var partDataBasis = DDP.GetPropertyValue("IJDPipeComponent", "PartDataBasis");//如果要取part上的某个属性，可以这样。和spf很像

                RunPDB11002(DDP, connection, oGemHelper);


            }
            catch (Exception ex) // General Unhandled exception
            {
                throw (ex);
            }
        }

        #endregion

        #region "Geometry Construction"
        /// <summary>
        /// 最初的模板，该函数是根据不同的partDataBasis的值，来进行不同的处理
        /// </summary>
        /// <param name="DDP"></param>
        /// <param name="connection"></param>
        private void RunPDB11002(PipeComponent DDP, SP3DConnection connection, SymbolGeometryHelper oGemHelper)
        {
            try
            {
                if (parEndPreparation3 == 301)
                {
                    parPressureRating3 = 1;
                }
            }
            catch
            {

            }

            try
            {
                // UtilityFunctions.CheckParameterForZeroValues(this, "FacetoFace");

                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD2, 0))
                {
                    MessageBox.Show("D2不能<=0");
                    throw new Exception("D2不能<=0");
                }
                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD8, 0))
                {
                    MessageBox.Show("D8不能<=0");
                    throw new Exception("D8不能<=0");
                }
                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD5, 0))
                {
                    MessageBox.Show("D5不能<=0");
                    throw new Exception("D5不能<=0");
                }
                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD6, 0))
                {
                    MessageBox.Show("D6不能<=0");
                    throw new Exception("D6不能<=0");
                }
                if (UtilityFunctions.CompareDoubleLessThanOrEqualTo(parD9, 0))
                {
                    MessageBox.Show("D9不能<=0");
                    throw new Exception("D9不能<=0");
                }

                if (parD4 <= parD7)  //UtilityFunctions.CompareDoubleGreaterThan()
                {
                    MessageBox.Show("D4 需要大于 D7");
                    throw new Exception("D4 需要大于 D7");
                }
                if (parD8 <= parD12)   
                {
                    MessageBox.Show("D8 需要大于 D12");
                    throw new Exception("D8 需要大于 D12");
                }
                double BodySize = 0.2;
                double NPD1, NPD3, b, c, d, e;


                // 第 1 个port
                // DDP 或者说 动态参数的情况，都要用这种方式先创建出port，而不能用下面这个
                // PipeNozzle port2 = PortHelper.CreatePipeNozzle(pipeComponent, connection, false, 2, new Position(0, D2, 0), new Vector(-1, 0, 0), true, true);
                PipeNozzle port1 = PortHelper.CreateDynamicPipePort(connection,
                                                                    1, parNpd1, parNpdUnitType1, parEndPreparation1, parScheduleThickness1, parEndStandard1, parPressureRating1, parFlowDirection1, parId1,
                                                                    defaultPartDataBasis, false, new Position(0, 0, 0), new Vector(-1, 0, 0), true, true);
                m_Physical.Outputs.Add("PNoz1", port1);  //Nozzle1
                UtilityFunctions.GetPipingPortData(DDP, port1, out NPD1, out b, out c, out d, out e, true);

                // 第 2 个port
                PipeNozzle port2 = PortHelper.CreateDynamicPipePort(connection, 2, parNpd2, parNpdUnitType2, parEndPreparation2, parScheduleThickness2, parEndStandard2, parPressureRating2, parFlowDirection2, parId2, defaultPartDataBasis, false, new Position(0, parD2, 0), new Vector(-1, 0, 0), true, true);
                m_Physical.Outputs.Add("PNoz2", port2);

                // 第 3 个port
                PipeNozzle port3 = PortHelper.CreateDynamicPipePort(connection, 3, parNpd3, parNpdUnitType3, parEndPreparation3, parScheduleThickness3, parEndStandard3, parPressureRating3, parFlowDirection3, parId3, defaultPartDataBasis, false, new Position(parD5, -parD9, 0), new Vector(0, -1, 0), true, true);
                m_Physical.Outputs.Add("PNoz3", port3);
                //上述创建Port后，可以拿到port具体的一些值
                UtilityFunctions.GetPipingPortData(DDP, port3, out NPD3, out b, out c, out d, out e, true);

                if (NPD3 > BodySize)
                {
                    BodySize = NPD3;
                }
                //if (parNpdUnitType3.ToUpper() == "IN")  //没必要了，因为GetPipingPortData可以直接拿到转换为m为单位的具体数值
                //{
                //    if (BodySize * 1000 > parNpd3 * 25.4)
                //    {
                //        BodySize = parNpd3 * 25.4 / 1000;
                //    }
                //}
                //else if (parNpdUnitType3.ToUpper() == "MM")
                //{
                //    if (BodySize * 1000 > parNpd3)
                //    {
                //        BodySize = parNpd3 / 1000;
                //    }
                //}

                // 第 1 个 主体圆柱 
                //Insert Code for Output1(Body)
                Position startPoint = new Position(parD5, -0.5 * parD9, 0);
                Position endPoint = new Position(parD5, parD2 + 0.7 * parD6, 0);
                var body = Graphics3D.CreateCylinder(startPoint, endPoint, BodySize, true);
                m_Physical.Outputs.Add("LeftCone", body);

                // 第 1 个 保温 
                body = Graphics3D.CreateCylinder(startPoint, endPoint, BodySize + 2 * parInsulationThickness, true);
                m_Insulation.Outputs.Add("InsulationCylinder", body);


                // 第 2 个 下方圆台
                Position centerBase = new Position(parD5, -0.5 * parD9, 0);  //大头
                Position centerTop = new Position(parD5, -parD9, 0);  //小头
                var body2 = Graphics3D.CreateCone(centerBase, centerTop, BodySize / 2, 0.6 * BodySize / 2, true);
                m_Physical.Outputs.Add("Cone1", body2);

                // 第 3 个 上方圆台 
                centerBase = new Position(parD5, parD2 + 0.7 * parD6, 0);  //大头
                centerTop = new Position(parD5, parD2 + parD6, 0);  //小头
                body2 = Graphics3D.CreateCone(centerBase, centerTop, BodySize / 2, 0.6 * BodySize / 2, true);
                m_Physical.Outputs.Add("Cone2", body2);

                // 第 4 个 像法兰一样的两片东西
                startPoint = new Position(parD5, parD2 + 0.3 * parD6, 0);
                endPoint = new Position(parD5, parD2 + 0.5 * parD6, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, 0.2 * parD5 + BodySize, true);
                m_Physical.Outputs.Add("Cylinder2", body);

                // 第 5 个 第一个port到主体的横向小圆柱
                startPoint = new Position(0, 0, 0);
                endPoint = new Position(parD5, 0, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, NPD1 / 3, true);
                m_Physical.Outputs.Add("Branch1", body);

                // 第 6 个 第二个port到主体的横向小圆柱
                startPoint = new Position(0, parD2, 0);
                endPoint = new Position(parD5, parD2, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, NPD1 / 3, true);
                m_Physical.Outputs.Add("Branch2", body);

                var height = parD2 + 0.6 * parD6;
                // 第 7 个 旋转的杆子（接主体的）
                startPoint = new Position(parD5, height, 0);
                endPoint = new Position(parD5 + parD4 * Math.Sin(parD10), height, -parD4 * Math.Cos(parD10));//长度由D7改为D4
                body = Graphics3D.CreateCylinder(startPoint, endPoint, 0.01, true);
                m_Physical.Outputs.Add("Branch3", body);

                // 第 8 个 旋转的杆子（接末端的小box）
                var BoxLenth = parD12; //parD8 / 2;
                var BoxWidth = 2 * (parD4 - parD7);
                startPoint = new Position(parD5 + parD7 * Math.Sin(parD10), height, -parD7 * Math.Cos(parD10));
                endPoint = new Position(startPoint.X + (parD8 - BoxLenth) * Math.Cos(parD10),
                                        startPoint.Y,
                                        startPoint.Z + (parD8 - BoxLenth) * Math.Sin(parD10));
                body = Graphics3D.CreateCylinder(startPoint, endPoint, 0.01, true);
                m_Physical.Outputs.Add("Branch4", body);

                //第 9 个，方块

                //起始基点
                oGemHelper.ActivePosition = new Position(endPoint.X, endPoint.Y, endPoint.Z);
                //基点的坐标系排列，-1，0，0 就是沿着x轴负方向。默认方向是1，0，0
                oGemHelper.SetOrientation(new Vector(Math.Cos(parD10), 0, Math.Sin(parD10)), oGemHelper.ActiveSecondary);
                body = oGemHelper.CreateBox(connection, BoxLenth, parD11, BoxWidth);


                m_Physical.Outputs.Add("Box", body);



            }
            catch (Exception ex) // General Unhandled exception
            {
                throw ex;
            }
        }


        #endregion

    }

}

